package com.trkj.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;


/**
 * 基础DAO，完成不变的部分<hr>
 * 几个方法：<br>
 * 1、获取Connection对象<br>
 * 2、将Connection对象还回连接池<br>
 * 3、执行insert、update和delete操作<br>
 * 4、执行查询select操作，将ResultSet转换List集合并通过接口返回 <br>
 * 注意：本类仅作为父类使用 
 * 测试测试……
 * 注意：本类仅作为父类使用
 * 李赞红 
 * @author Administrator
 *
 */
public class BaseDAO {
	public static final String DEFAULT_NAME = "jdbc/tr09";
	
	private String contextName;// 连接池的名称，比如jdbc/tr09
	
	public BaseDAO() {
		this(DEFAULT_NAME);
	}

	public BaseDAO(String contextName) {
		super();
		this.contextName = contextName;
	}

	/**
	 * 获取连接对象
	 * @return
	 */
	private Connection getConnection(){
		try {
			//创建上下文环境
			Context ctx = new InitialContext();
			//查找连接池
			DataSource ds = (DataSource)ctx.lookup(
					"java:comp/env/" + contextName);
			//获取连接对象
			Connection conn = ds.getConnection();
			return conn;
		} catch (NamingException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 将连接对象还回连接池
	 * @param conn
	 * @param stmt
	 * @param rs
	 */
	private void close(Connection conn, Statement stmt,
			ResultSet rs){
		if(rs != null){
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
		if(stmt != null){
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
		if(conn != null){
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 执行insert、update和delete语句<br>
	 * insert into student(sname, birthday, c_id) values(?,?,?)
	 * @param sql SQL语句
	 * @param params 参数值，数组
	 */
	public void executeUpdate(String sql, Object...params){
		Connection conn = getConnection();
		PreparedStatement stmt = null;
		if(conn != null){
			try {
				stmt = 
						conn.prepareStatement(sql);
				bindParameters(stmt, params);
				//执行
				stmt.executeUpdate();
			} catch (SQLException e) {
				e.printStackTrace();
			} finally{
				close(conn, stmt, null);
			}
			
		}
	}
	
	/**
	 * select * from classes where cid=? and cname=?
	 * @param sql
	 * @param params
	 */
	public <T> List<T> executeQuery(String sql, 
			RowMapper<T> rowMapper,
			Object...params){
		Connection conn = getConnection();
		PreparedStatement stmt = null;
		ResultSet rs = null;
		if(conn != null){
			try {
				stmt = conn
						.prepareStatement(sql);
				bindParameters(stmt, params);
				rs = stmt.executeQuery();
				//将rs转换成JavaBean的List集合
				if(rs != null){
					List<T> list = new ArrayList<T>();
					while(rs.next()){
						//将ResultSet中的当前行转换为T对象
						T t = rowMapper.mapper(rs);
						list.add(t);
					}
					return list;
				}
			} catch (SQLException e) {
				e.printStackTrace();
			} finally {
				close(conn, stmt, rs);
			}
		}
		return null;
	}
	
	/**
	 * 根据id查找记录
	 * @param sql
	 * @param rowMapper
	 * @param params
	 * @return
	 */
	public <T> T get(String sql, 
			RowMapper<T> rowMapper, 
			Object...params){
		Connection conn = getConnection();
		PreparedStatement stmt = null;
		ResultSet rs = null;
		try {
			stmt =
					conn.prepareStatement(sql);
			bindParameters(stmt, params);
			rs = stmt.executeQuery();
			if(rs != null && rs.next()){
				T t = rowMapper.mapper(rs);
				return t;
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			close(conn, stmt, rs);
		}
		return null;
	}

	/**
	 * 绑定参数
	 * @param stmt
	 * @param params
	 * @throws SQLException
	 */
	private void bindParameters(PreparedStatement stmt, Object... params) throws SQLException {
		//绑定参数
		if(params != null){
			for(int i = 0; i < params.length; i ++){
				stmt.setObject(i + 1, params[i]);
			}
		}
	}
}





